package com.tccmeta.servlce;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tccmeta.mapper.MetaMapper;
import com.tccmeta.mapper.MetaRelationDataMapper;
import com.tccmeta.mapper.MetaRelationMapper;
import com.tccmeta.po.Meta;
import com.tccmeta.po.MetaRelation;
import lombok.extern.java.Log;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.script.ScriptException;
import java.util.*;

import static com.tccmeta.constants.MetaConstants.*;


/**
 * @author pan
 * @date 2021/5/13 10:18
 */
@Service
@Log
public class MetaService {
    @Resource
    MetaRelationDataMapper metaRelationDataMapper;
    @Resource
    MetaMapper metaMapper;
    @Resource
    MetaRelationMapper metaRelationMapper;

    /**
     * 分页查询
     */
    public Page<Meta> findPage(Page<Map<?, ?>> page, Meta meta) {
        Page<Map<String, Object>> mapPage = metaRelationDataMapper.findPage(page, meta);
        List<Map<String, Object>> records = mapPage.getRecords();
        List<Meta> metas = new ArrayList<>();
        records.forEach((e) -> {
            Meta item = this.mapToCondition(e, meta, null);
            metas.add(item);
        });
        Page<Meta> result = new Page<>(mapPage.getCurrent(), mapPage.getSize(), mapPage.getTotal());
        result.setRecords(metas);
        return result;
    }

    /**
     * 保存
     */
    @Transactional(rollbackFor = Exception.class)
    public Meta save(Meta meta) throws ScriptException {
        if (meta.getId() != null) {
            metaMapper.updateById(meta);
        } else {
            meta.setId(IdUtil.getSnowflake().nextId());
            metaMapper.insert(meta);
        }
        List<Meta> childes = meta.getRelations();
        if (childes != null && childes.size() > 0) {
            for (Meta item : childes) {
                this.save(item);
                this.saveRelation(item.getId(), meta.getId());
            }
        }
        return meta;
    }

    public void delete(Meta Meta) {
        metaMapper.deleteById(Meta.getId());
        QueryWrapper<MetaRelation> deleteWrapper = new QueryWrapper<>();
        deleteWrapper.lambda().eq(MetaRelation::getMetaId, Meta.getId()).or().eq(MetaRelation::getRelatedMetaId, Meta.getId());
        metaRelationMapper.delete(deleteWrapper);
        List<Meta> childes = Meta.getRelations();
        if (childes != null && childes.size() > 0) {
            for (Meta item : childes) {
                if (item.getId() != null && item.getId() != 0) {
                    this.delete(item);
                }
            }
        }
    }


    public void saveRelation(long metaId, long relatedMetaId) {
        QueryWrapper<MetaRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MetaRelation::getMetaId, metaId);
        queryWrapper.lambda().eq(MetaRelation::getRelatedMetaId, relatedMetaId);
        MetaRelation metaRelation = metaRelationMapper.selectOne(queryWrapper);
        if (metaRelation == null) {
            metaRelation = MetaRelation.builder().build();
            metaRelation.setId(IdUtil.getSnowflake().nextId());
            metaRelation.setMetaId(metaId);
            metaRelation.setRelatedMetaId(relatedMetaId);
            metaRelationMapper.insert(metaRelation);
        }
    }

    public void deleteRelation(long metaId, long relatedMetaId) {
        QueryWrapper<MetaRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MetaRelation::getMetaId, metaId);
        queryWrapper.lambda().eq(MetaRelation::getRelatedMetaId, relatedMetaId);
        metaRelationMapper.delete(queryWrapper);
    }

    /**
     * 从数据库中查询出的一维数据转为多维结构数据 递归
     *
     * @param map 一维数据
     * @return 节点
     */
    private Meta mapToCondition(Map<?, ?> map, Meta meta, String topOneDimensional) {
        Meta result = Meta.builder().relations(new ArrayList<>()).build();
        String oneDimensional = String.valueOf(meta.getOneDimensional());
        if (topOneDimensional != null) {
            oneDimensional = topOneDimensional + oneDimensional;
        }
        result.setOneDimensional(meta.getOneDimensional());
        Object dataObject = map.get(MAP_KEY_DATA + oneDimensional);
        result.setData(dataObject);
        Object idObject = map.get(MAP_KEY_ID + oneDimensional);
        result.setId(idObject == null ? null : (Long) idObject);
        Object aliasObject = map.get(MAP_KEY_ALIAS + oneDimensional);
        result.setAlias(aliasObject == null ? "" : (String) aliasObject);
        Object typeObject = map.get(MAP_KEY_TYPE + oneDimensional);
        result.setType(typeObject == null ? "" : (String) typeObject);
        List<Meta> relations = meta.getRelations();
        if (relations != null && relations.size() > 0) {
            for (Meta item : relations) {
                relations.add(mapToCondition(map, item, oneDimensional));
            }
        }
        return result;
    }
}
